package com.kai.service.ipml;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.kai.Util.HttpUtil;
import com.kai.dto.ScriptPubKey;
import com.kai.dto.WalletUsdtResponseDTO;
import com.kai.entity.*;
import com.kai.mapper.second.WalletColdMapper;
import com.kai.mapper.second.WalletHotMapper;
import com.kai.mapper.second.WalletPlatformMapper;
import com.kai.mapper.second.WalletPreinstallAddressMapper;
import com.kai.mapper.third.WalletBlockHeightMapper;
import com.kai.mapper.third.WalletFinanceMapper;
import com.kai.mapper.third.WalletTransactionRecordMapper;
import com.kai.service.UsdtServie;
import com.kai.service.WalletService;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * usdt操作
 * @author zhangkai
 * @create 2018/6/7
 **/
@Service("UsdtServie")
public class UsdtServiceImpl implements UsdtServie {

    private Logger log = LoggerFactory.getLogger(UsdtServiceImpl.class);

    private final static String RESULT = "result";
    private final static String METHOD_SEND_TO_ADDRESS = "omni_send";
    private final static String METHOD_GET_TRANSACTION = "omni_gettransaction";
    private final static String METHOD_GET_BLOCK_COUNT = "getblockcount";
    private final static String METHOD_NEW_ADDRESS = "getnewaddress";
    private final static String METHOD_GET_BALANCE = "omni_getbalance";
    private final static String METHOD_GET_LISTBLOCKTRANSACTIONS = "omni_listblocktransactions";
    private final static String METHOD_GETTRADE= "omni_gettrade";
    private final static String CONTINER_USDT= "USDT";
    private final static String WithdrawStatetype= "3";
    private final static String METHOD_GET_RAWTRANSACTION= "getrawtransaction";
    /**
     * 1:用户充值；2:提币;3:冷钱包到提币热钱包，4:未知地址到冷钱包，5:未知地址到提币热钱包，
     6:资金归集；7:平台预设地址到冷钱包，8:充值钱包资金归集的手续费地址收币
     *
     */
    private final static String TYPE_ONE= "1";
    private final static String TYPE_TWO= "2";
    private final static String TYPE_THREE= "3";
    private final static String TYPE_FOUR= "4";
    private final static String TYPE_FIVE= "5";
    private final static String TYPE_SIX= "6";
    private final static String TYPE_SEVEN= "7";
    private final static String TYPE_EIGHT= "8";
    //充值节点
    private final static Integer WLLETID= 1;
    //提现节点
    private final static Integer WLLETIDT= 2;

    private final static String VERSION= "2";

    private final static String COIN_TYPE_USDT= "1";
    private final static String COIN_TYPE_BITCOIN= "2";




    private final static double FLOWNEXTBITCOIN = 0.00000546;//流入接收地址的bitcoin

    @Resource
    private RedisService redisService;
    @Resource
    private WalletHotMapper walletHotMapper;

    @Autowired
    private WalletService walletService;
    @Resource
    private WalletColdMapper walletColdMapper;

    @Resource
    private WalletPlatformMapper walletPlatformMapper;

    @Resource
    private WalletPreinstallAddressMapper walletPreinstallAddressMapper;

    @Resource
    private WalletBlockHeightMapper walletBlockHeightMapper;

    @Resource
    private WalletTransactionRecordMapper walletTransactionRecordMapper;

    @Resource
    private WalletFinanceMapper walletFinanceMapper;

    @Value("${spring.usdt.combinelimit}")
    private double combinelimit;

    @Value("${spring.usdt.propertyid}")
    private int propertyId = 31;

    @Value("${spring.usdt.username}")
    private String username;

    @Value("${spring.usdt.password}")
    private String password;

    @Value("${spring.usdt.url}")
    private String url;

    @Value("${spring.usdtwithdraw.username}")
    private String usernameWithdraw;

    @Value("${spring.usdtwithdraw.password}")
    private String passwordWithdraw;

    @Value("${spring.usdtwithdraw.url}")
    private String urlWithdraw;

    @Value("${spring.usdt.walletphrase}")
    private String walletPhrase;

    @Value("${spring.usdt.usdtfee}")
    private double usdtfee; //转账手续费


    // USDT产生地址
    @Autowired
    public String getNewAddress(){
        JSONObject json;
        try {
            json = doRequest(METHOD_NEW_ADDRESS);
            if(isError(json)){
                log.error("获取USDT地址失败:{}",json.get("error"));
                return "";
            }
            return json.getString(RESULT);
        }catch (Exception e){
            log.error(e.getMessage());
        }
        return "";
    }

    /**
     * USDT查询余额
     * @return
     */
    public JSONObject getBalance(String addr){
        Map<Object,Object> m=new HashMap<>();
        JSONObject json = doRequest(METHOD_GET_BALANCE,addr,propertyId);
        if(isError(json)){
            log.error("获取USDT余额:{}",json.get("error"));
            return json;
        }

        return json;
        //return BigDecimalUtil.inputConvert(json.getJSONObject(RESULT).getDouble("balance"));
    }

    @Override
    public void merge() {

    }

    @Override
    public int lastBlockHeight(int id, int height) {
        try {
            WalletBlockHeight info=walletBlockHeightMapper.selectByPrimaryKey(id);
            if(info==null){
                return height-1;
            }
            return info.getBlockHeigth();
        }catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return 0;
        }
    }

    private  Boolean getBlockHeightInfo(int id){
        try {
            WalletBlockHeight info=walletBlockHeightMapper.selectByPrimaryKey(id);
            if(info !=null && info.getFlag().equals(false)){
                return true;
            }
            return false;
        }catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return true;
        }

    }

    @Override
    public boolean parseBlock(int index) {
        return false;
    }


    //验证地址的有效性
    @Override
    public boolean vailedAddress(String address) {
        JSONObject json  = doRequest("validateaddress",address);
        if(isError(json)){
            log.error("USDT验证地址失败:",json.get("error"));
            return false;
        }else{
            return json.getJSONObject(RESULT).getBoolean("isvalid");
        }
    }


    //区块高度
    @Override
    public int getBlockCount(){
        JSONObject json = null;
        try {
            json = doRequest(METHOD_GET_BLOCK_COUNT);
            if(!isError(json)){
                return json.getInteger("result");
            }else{
                log.error(json.toString());
                return 0;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    //提现节点区块高度
    @Override
    public int getBlockCountWithdraw(){
        JSONObject json = null;
        try {
            json = doRequestWithdraw(METHOD_GET_BLOCK_COUNT);
            if(!isError(json)){
                return json.getInteger("result");
            }else{
                log.error(json.toString());
                return 0;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    // error 处理
    private boolean isError(JSONObject json){
        if( json == null || (StringUtils.isNotEmpty(json.getString("error")) && json.get("error") != "null")){
            return true;
        }
        return false;
    }

    /**
     * 充值节点
     * 发送请求
     * @param method
     * @param params
     * @return
     */
    private JSONObject doRequest(String method,Object... params){
        JSONObject param = new JSONObject();
        param.put("id",System.currentTimeMillis()+"");
        param.put("jsonrpc","2.0");
        param.put("method",method);
        if(params != null){
            param.put("params",params);
        }
        String creb = Base64.encodeBase64String((username+":"+password).getBytes());
        Map<String,String> headers = new HashMap<>(2);
        headers.put("Authorization","Basic "+creb);
        return JSON.parseObject(HttpUtil.jsonPost(url,headers,param.toJSONString()));
    }

    /**
     * 提现节点连接
     * @param method
     * @param params
     * @return
     */
    private JSONObject doRequestWithdraw(String method,Object... params){
        JSONObject param = new JSONObject();
        param.put("id",System.currentTimeMillis()+"");
        param.put("jsonrpc","2.0");
        param.put("method",method);
        if(params != null){
            param.put("params",params);
        }
        String creb = Base64.encodeBase64String((usernameWithdraw+":"+passwordWithdraw).getBytes());
        Map<String,String> headers = new HashMap<>(2);
        headers.put("Authorization","Basic "+creb);
        return JSON.parseObject(HttpUtil.jsonPost(urlWithdraw,headers,param.toJSONString()));
    }


    @Override
    public String createpayload(String amount){
        // todo
        // 判断用户是否有足够 amount usdt

        JSONObject json = doRequest("omni_createpayload_simplesend",propertyId,amount);
        if(isError(json)){
            log.error("创建payload失败：",amount,json.get("error"));
            return "";
        }else {
            return json.getString(RESULT);
        }
    }

    @Override
    public String createrawtransaction(String address_from) {
        return null;
    }


    @Override
    public String attachPayloadOutput(String txHex, String payload){
        JSONObject json = doRequest("omni_createrawtx_opreturn",txHex,payload);
        if(isError(json)){
            log.error("负载输出贴到原始交易：",json.get("error"));
            return "";
        }else {
            return json.getString(RESULT);
        }
    }
    @Override
    public String txReference(String rawtx, String destination){
        JSONObject json = doRequest("omni_createrawtx_reference",rawtx,destination);
        if(isError(json)){
            log.error("负载输出贴到原始交易：",json.get("error"));
            return "";
        }else {
            return json.getString(RESULT);
        }
    }

    @Override
    public String txCharge(String tx, String changeAddress) {
        return null;
    }


    @Override
    // 列出区块所有usdt交易
    public JSONObject listBlockUsdttx(long height){
        JSONObject json  = doRequest(METHOD_GET_LISTBLOCKTRANSACTIONS,height);
        if(isError(json)){
            log.error("omni_listblocktransactions error");
        }
        return json;
    }

    private JSONObject listBlockUsdttxWithdraw(long height){
        JSONObject json  = doRequestWithdraw(METHOD_GET_LISTBLOCKTRANSACTIONS,height);
        if(isError(json)){
            log.error("omni_listblocktransactions error");
        }
        return json;
    }



    /**
     * usdt 交易详情
     */
    @Override
    public JSONObject txDetails(String txid){
        JSONObject json  = doRequest(METHOD_GETTRADE,txid);
        if(isError(json)){
            log.error("omni_gettrade error");
        }
        return json;
    }

    /**
     * 提现节点解析交易
     * @param txid
     * @return
     */
    @Override
    public JSONObject txDetailsWithdraw(String txid){
        JSONObject json  = doRequestWithdraw(METHOD_GETTRADE,txid);
        if(isError(json)){
            log.error("omni_gettrade error");
        }
        return json;
    }


    @Override
    //地址对应的usdt
    public JSONObject balanceByAddress(String address){
        int propertyid = propertyId;
        JSONObject json  = doRequest("omni_getbalance",address, propertyid);
        if(isError(json)){
            log.error("omni_getbalance error");
        }
        return json;
    }

    /**
     * rawTransaction
     * @param txid
     * @return
     */
    public JSONObject getRawTransaction(String txid){
        boolean format = true;
        JSONObject json  = doRequest(METHOD_GET_RAWTRANSACTION,txid, 1);
        if(isError(json)){
            log.error("getrawtransaction:",json.get("error"));
        }
        return json;
    }

    /**
     * 提现节点
     * rawTransaction
     * @param txid
     * @return
     */
    public JSONObject getRawTransactionWithdraw(String txid){
        boolean format = true;
        JSONObject json  = doRequestWithdraw(METHOD_GET_RAWTRANSACTION,txid, 1);
        if(isError(json)){
            log.error("getrawtransaction:",json.get("error"));
        }
        return json;
    }


    /**
     * USDT 充值节点扫块
     * 交易信息格式
     *{
     *   "txid": "82f61d8bcd0ccc2a66d33e3704c29e1e87942e0e30c2f07d15b2baea8fb3c64d",
     *   "fee": "0.00002000",
     *   "sendingaddress": "37Tm3Qz8Zw2VJrheUUhArDAoq58S6YrS3g",
     *   "referenceaddress": "14AwtvmKGxpxcA2Ey2jcNxGk9TpQMgqHtT",
     *   "ismine": false,
     *   "version": 0,
     *   "type_int": 0,
     *   "type": "Simple Send",
     *   "propertyid": 31,
     *   "divisible": true,
     *   "amount": "28320.44700000",
     *   "valid": true,
     *   "blockhash": "0000000000000000000c3f4576d6798b65c19b6ea728c45d79d703ae3b322cc1",
     *   "blocktime": 1531738223,
     *   "positioninblock": 2080,
     *   "block": 532143,
     *   "confirmations": 74
     * }
     */
    @Override
    public Boolean blockScanUsdt(){
        Long startTime = System.currentTimeMillis();
        Map<String,Object> addressHotMap=new HashMap<>();
        Map<String,Object> addressColdMap=new HashMap<>();
        Map<String,Object> addressPlatformMap=new HashMap<>();
        //平台预设地址
        Map<String,Object> addressPreinstallMap=new HashMap<>();

        //平台中热钱包的地址
        try {
            addressHotMap=this.getHotAddress(CONTINER_USDT);
            addressColdMap=this.getColdAddress(CONTINER_USDT);
            addressPlatformMap=this.getPlatAddress(CONTINER_USDT);
            addressPreinstallMap=this.getPreinstall();
            //区块当前高度
            int height=getBlockCount();
            if(getBlockHeightInfo(1)){
                log.info("扫块已经关闭");
                return true;
            }
            //上一次扫的高度
            int lastBlockHeight=lastBlockHeight(1,height);
            log.info("bte当前高度是：{} 处理记录高度：{}",height,lastBlockHeight);
            int number=height-lastBlockHeight;
            for(int k=0;k<number;k++) {
                lastBlockHeight++;
                //根据高度查询区块信息
                JSONObject Usdtobject = listBlockUsdttx(lastBlockHeight);
                JSONArray UsdtJsonArray = Usdtobject.getJSONArray("result");
                if (!Usdtobject.isEmpty() && UsdtJsonArray.size() > 0 && Usdtobject.getString("result") != null && StringUtils.isNotEmpty(Usdtobject.getString("result"))) {
                    //遍历tx_id
                    for (int i = 0; i < UsdtJsonArray.size(); i++) {
                        //根据tx_id查询交易信息
                        JSONObject listObject = txDetails(UsdtJsonArray.get(i).toString());

                        //判断是否是USDT数据
                        if (isError(listObject)) {
                            log.error("处理USDT tx出错");
                            continue;
                        }
                        JSONObject jsonTResult = listObject.getJSONObject(RESULT);
                        if (!jsonTResult.getBoolean("valid")) {
                            log.info("不是有效数据");
                            continue;
                        }
                        int propertyidResult = jsonTResult.getIntValue("propertyid");
                        if (propertyidResult != propertyId) {
                            log.info("非USDT数据");
                            continue;
                        }
                        WalletUsdtResponseDTO wrd = JSON.parseObject(listObject.getString("result"), WalletUsdtResponseDTO.class);
                        //存入热钱包记录
                        if (wrd != null && wrd.getReferenceaddress() != null && addressHotMap.get(wrd.getReferenceaddress()) != null) {
                            double free = getSendBitcoin(UsdtJsonArray.get(i).toString(), wrd.getReferenceaddress());
                            wrd.setSendtoaddressFree(String.valueOf(new DecimalFormat().format(free * Math.pow(10, 8)).replace(",", "")));
                            wrd.setTx_type(TYPE_ONE);
                            insertWalletTxList(wrd);
                        }
                        //资金归集 商户热钱包往平台冷钱包中转,热钱包在vin中，冷钱包在vout中
                        if (wrd != null && addressHotMap.get(wrd.getSendingaddress()) != null && addressColdMap.get(wrd.getReferenceaddress()) != null) {
                            double free = getSendBitcoin(UsdtJsonArray.get(i).toString(), wrd.getReferenceaddress());
                            wrd.setSendtoaddressFree(String.valueOf(new DecimalFormat().format(free * Math.pow(10, 8)).replace(",", "")));
                            wrd.setTx_type(TYPE_SIX);
                            insertWalletTxList(wrd);
                        }
                        //充值钱包资金归集的手续费地址收币

                    }
                }
            }
            //更新记录的区块高度
           if(blockheight(lastBlockHeight)) {
                log.info("剩余多少块未扫：{}",height - lastBlockHeight);
            }
            log.info("扫块结束时间：{}",System.currentTimeMillis() - startTime);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            log.error("扫块数据插入失败:{}",false);
            return true;
        }
    }

    //添加比特币来源
    private double getSendBitcoin(String txid,String sendToddress){
        double sendBitcoin=0.00000000;
        try {
            JSONObject json=getRawTransaction(txid);
            //根据tx_id查询交易信息
            if(json !=null){
                JSONObject TxObj = getRawTransaction(txid).getJSONObject(RESULT);
                //输出地址voutaddress
                JSONArray vout = TxObj.getJSONArray("vout");
                if (vout!=null && vout.size() > 0) {
                    for (int j = 0; j < vout.size(); j++) {
                        //vout对象
                        String sp = vout.getJSONObject(j).getString("scriptPubKey");
                        ScriptPubKey scriptPubKey = JSON.parseObject(sp, ScriptPubKey.class);
                        if(scriptPubKey !=null && scriptPubKey.getAddresses() != null){
                            //存入商户热钱包
                            if ((scriptPubKey.getAddresses().toString()).replaceAll("\\[|\\]", "").equals(sendToddress)) {
                                sendBitcoin =Double.parseDouble( vout.getJSONObject(j).getString("value"));
                                return sendBitcoin;
                            }
                        }
                    }
                }
            }

        }catch (Exception e){
            e.printStackTrace();
            log.error("解析txid失败：{}",e.getMessage());
            return  sendBitcoin;
        }
        return sendBitcoin;
    }
    /**
     * 提现节点扫块
     * @return
     */
    @Transactional
    @Override
    public Boolean blockScanUsdtWithdraw(){

        Long startTime = System.currentTimeMillis();
        Map<String,Object> addressmap=new HashMap<>();
        Map<String,Object> addressColdMap=new HashMap<>();
        Map<String,Object> addressPlatformMap=new HashMap<>();
        //平台预设地址
        Map<String,Object> addressPreinstallMap=new HashMap<>();
        List<WalletUsdtResponseDTO> listusdt=new ArrayList<>();

        try {
            //平台中热钱包的地址
            addressmap=this.getHotAddress("USDT");
            addressColdMap=this.getColdAddress("USDT");
            addressPlatformMap=this.getPlatAddress("USDT");
            addressPreinstallMap=getPreinstall();
            if(getBlockHeightInfo(2)){
                log.info("扫块已经关闭");
                return true;
            }
            //当前区块高度
            int height=getBlockCountWithdraw();
            int lastBlockHeight=lastBlockHeight(2,height);
            log.info("bte当前高度是：{} 处理记录高度：{}",height,lastBlockHeight);
            int blockNumber=height-lastBlockHeight;

            for(int k=0;k<blockNumber;k++){
                lastBlockHeight++;
                //根据高度查询区块信息
                JSONObject Usdtobject=listBlockUsdttxWithdraw(lastBlockHeight);
                JSONArray UsdtJsonArray=Usdtobject.getJSONArray("result");
                if(!Usdtobject.isEmpty() && UsdtJsonArray.size()>0 && Usdtobject.getString("result")!=null && StringUtils.isNotEmpty(Usdtobject.getString("result"))){
                    //遍历tx_id
                    for (int i=0;i<UsdtJsonArray.size();i++){
                        //根据tx_id查询交易信息
                        JSONObject listObject=txDetailsWithdraw(UsdtJsonArray.get(i).toString());

                        //判断是否是USDT数据
                        if(isError(listObject)) {
                            log.error("处理USDT tx出错");
                            continue;
                        }
                        JSONObject jsonTResult = listObject.getJSONObject(RESULT);
                        if (!jsonTResult.getBoolean("valid")) {
                            log.info("不是有效数据");
                            continue;
                        }
                        int propertyidResult = jsonTResult.getIntValue("propertyid");
                        if (propertyidResult!=propertyId) {
                            log.info("非USDT数据");
                            continue;
                        }

                        WalletUsdtResponseDTO wrd = JSON.parseObject(listObject.getString("result"), WalletUsdtResponseDTO.class);

                        //更wallet_platform_out的提现状态
                       /* if(updatewalletPlatformOut(UsdtJsonArray.get(i).toString().trim())){
                            continue;
                        }*/
                        //提币,平台热钱包在vin中,平台地址不在vout中
                        if(wrd!=null && wrd.getSendingaddress()!=null && addressPlatformMap.get(wrd.getSendingaddress()) !=null && addressColdMap.get(wrd.getReferenceaddress()) ==null && addressPreinstallMap.get(wrd.getReferenceaddress())==null&& addressPlatformMap.get(wrd.getReferenceaddress())==null){
                            double free=getSendBitcoinWithdraw(UsdtJsonArray.get(i).toString(),wrd.getReferenceaddress());
                            wrd.setSendtoaddressFree(String.valueOf(new DecimalFormat().format(free*Math.pow(10,8)).replace(",","")));
                            wrd.setTx_type(TYPE_TWO);
                            insertWalletTxList(wrd);
                            continue;
                        }
                        //clod->平台预设地址 冷钱包地址vin中，冷钱包和热钱包地址都不在vout中,平台预设地址在vout中
                        if(wrd!=null && wrd.getSendingaddress()!=null && addressColdMap.get(wrd.getSendingaddress()) !=null && addressPreinstallMap.get(wrd.getSendingaddress()) ==null && addressPreinstallMap.get(wrd.getReferenceaddress())!=null){
                            double free=getSendBitcoinWithdraw(UsdtJsonArray.get(i).toString(),wrd.getReferenceaddress());
                            wrd.setSendtoaddressFree(String.valueOf(new DecimalFormat().format(free*Math.pow(10,8)).replace(",","")));
                            wrd.setTx_type(TYPE_SEVEN);
                            insertWalletTxList(wrd);
                            continue;
                        }
                        //clod->提币热钱包  冷钱包在vin中，热钱包在vout中
                        if(wrd!=null && wrd.getSendingaddress()!=null && addressColdMap.get(wrd.getSendingaddress()) !=null && addressPlatformMap.get(wrd.getReferenceaddress()) !=null){
                            double free=getSendBitcoinWithdraw(UsdtJsonArray.get(i).toString(),wrd.getReferenceaddress());
                            wrd.setSendtoaddressFree(String.valueOf(new DecimalFormat().format(free*Math.pow(10,8)).replace(",","")));
                            wrd.setTx_type(TYPE_THREE);
                            insertWalletTxList(wrd);
                            continue;
                        }
                        //未知地址->cold 未知地址在vin中,冷钱包地址在vout中
                        if(wrd!=null && wrd.getReferenceaddress()!=null && addressColdMap.get(wrd.getReferenceaddress()) !=null && addressColdMap.get(wrd.getSendingaddress()) ==null && addressPlatformMap.get(wrd.getSendingaddress()) ==null && addressmap.get(wrd.getSendingaddress()) ==null){
                            double free=getSendBitcoinWithdraw(UsdtJsonArray.get(i).toString(),wrd.getReferenceaddress());
                            wrd.setSendtoaddressFree(String.valueOf(new DecimalFormat().format(free*Math.pow(10,8)).replace(",","")));
                            wrd.setTx_type(TYPE_FOUR);
                            insertWalletTxList(wrd);
                            continue;
                        }
                        //未知地址->提币热钱包 未知地址在vin中,热钱包地址在vout中
                        if(wrd!=null && wrd.getReferenceaddress()!=null && addressPlatformMap.get(wrd.getReferenceaddress()) !=null && addressColdMap.get(wrd.getSendingaddress()) ==null && addressPlatformMap.get(wrd.getSendingaddress()) ==null){
                            double free=getSendBitcoinWithdraw(UsdtJsonArray.get(i).toString(),wrd.getReferenceaddress());
                            wrd.setSendtoaddressFree(String.valueOf(new DecimalFormat().format(free*Math.pow(10,8)).replace(",","")));
                            wrd.setTx_type(TYPE_FIVE);
                            insertWalletTxList(wrd);
                        }

                    }
                }
                //更新记录的区块高度
                if(blockheightWithdraw(lastBlockHeight)) {
                    log.info("剩余多少块未扫：{}",height - lastBlockHeight);
                }
            }
            log.info("扫块结束时间：{}",System.currentTimeMillis() - startTime);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            log.error("扫块数据插入失败:{}",listusdt);
            return false;
        }
    }

    /**
     * 冷钱包地址
     */
    @Override
    public Map<String, Object> getColdAddress(String accountType) {
        Map<String,Object> addressColdMap=new HashMap<>();
        WalletCold wc = new WalletCold();
        wc.setAccountType(accountType);
        wc.setUseStatus(true);
        List<WalletCold> list=walletColdMapper.selectWalletAddressList(wc);
        //平台中的地址
        if(list !=null && list.size()>0){
            for (WalletCold wp: list) {
                addressColdMap.put(wp.getWalletAddressHash(),wp);
            }
        }
        return addressColdMap;
    }

    /**
     * 平台热钱包地址
     * @param accountType
     * @return
     */
    @Override
    public Map<String, Object> getPlatAddress(String accountType) {
        Map<String,Object> addressHotMap=new HashMap<>();
        WalletPlatform w = new WalletPlatform();
        w.setAccountType(accountType);
        w.setUseStatus(true);
        w.setExpireState(false);
        w.setPageNum(1);
        w.setPageSize(100000000);
        List<WalletPlatform> list=walletPlatformMapper.selectWalletPlatformsList(w);
        //平台中的地址
        if(list !=null && list.size()>0){
            for (WalletPlatform wp: list) {
                addressHotMap.put(wp.getWalletAddressHash(),wp);
            }
        }
        return addressHotMap;

    }

    /**
     * 平台商户热钱包地址
     * @param accountType
     * @return
     */
    @Override
    public Map<String, Object> getHotAddress(String accountType) {
        Map<String,Object> addressHotMap=new HashMap<>();
        WalletHot wh = new WalletHot();
        wh.setAccountType(accountType);
        wh.setUseStatus(true);
        wh.setExpireState(false);
        try{
            List<WalletHot> list=walletHotMapper.selectWalletAddressList(wh);
            if(list !=null && list.size()>0){
                for (WalletHot wp: list) {
                    addressHotMap.put(wp.getWalletAddressHash(),wp);
                }
            }
            return addressHotMap;
        }catch (Exception e){
            e.printStackTrace();
            return addressHotMap;
        }
    }

    /**
     *
     *平台预设地址
     */
    @Override
    public Map<String,Object> getPreinstall(){
        Map<String,Object> addressPreinstllMap=new HashMap<>();
        List<WalletPreinstallAddress> listPlat=walletPreinstallAddressMapper.selectWalletPreinstallAddressmList(new WalletPreinstallAddress());
        //平台中的地址
        if(listPlat !=null && listPlat.size()>0){
            for (WalletPreinstallAddress wp: listPlat) {
                addressPreinstllMap.put(wp.getWalletAddressHash(),wp);
            }
        }
        return  addressPreinstllMap;

    }

    /**
     * 数据库中的高度
     */
   private Boolean blockheight(int lastBlockHeight){

        WalletBlockHeight wbp=new WalletBlockHeight();
        wbp.setBlockHeigth(lastBlockHeight);
        wbp.setUpdateTime(System.currentTimeMillis());
        wbp.setId(1);
        try {
            WalletBlockHeight bpo= walletBlockHeightMapper.selectByPrimaryKey(1);
            if(bpo !=null){
                walletBlockHeightMapper.updateByPrimaryKeySelective(wbp);
            }else{
                walletBlockHeightMapper.insertSelective(wbp);
            }
            return  true;
        }catch (Exception e){
            e.printStackTrace();
            log.error("更新区块高度失败：{}",e.getMessage());
            return  false;
        }
    }

    private Boolean blockheightWithdraw(int lastBlockHeight){

        WalletBlockHeight wbp=new WalletBlockHeight();
        wbp.setBlockHeigth(lastBlockHeight);
        wbp.setUpdateTime(System.currentTimeMillis());
        wbp.setId(2);
        try {
            WalletBlockHeight bpo= walletBlockHeightMapper.selectByPrimaryKey(2);
            if(bpo !=null){
                walletBlockHeightMapper.updateByPrimaryKeySelective(wbp);
            }else{
                walletBlockHeightMapper.insertSelective(wbp);
            }
            return  true;
        }catch (Exception e){
            e.printStackTrace();
            log.error("更新区块高度失败：{}",e.getMessage());
            return  false;
        }
    }
    /**
     * 存储交易记录
     */
    private void insertWalletFinanceList(WalletTransactionRecord wrd){
        WalletFinance wf=new WalletFinance();
        try{
            BeanUtils.copyProperties(wrd,wf);
            //存入数据库
            if(this.getFinanceList(wf) !=null && this.getFinanceList(wf).size()>0){
                wf.setEntryId(this.getFinanceList(wf).get(0).getEntryId());
                walletFinanceMapper.updateByPrimaryKey(wf);
            }else{
                walletFinanceMapper.insert(wf);
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error("存入数据失败：{}",e.getMessage());
        }

    }

    /**
     * 存储财务报表交易记录
     */
    private void insertWalletTxList(WalletUsdtResponseDTO wrd){
        WalletTransactionRecord wtr=new WalletTransactionRecord();
        try{
            BeanUtils.copyProperties(wrd,wtr);
            wtr.setToAddress(wrd.getReferenceaddress());
            wtr.setCreateTime(System.currentTimeMillis());
            wtr.setBlockHeight(wrd.getBlock().intValue());
            wtr.setAmount(wrd.getAmount().toString());
            wtr.setBlockTime(wrd.getBlocktime());
            wtr.setFromAddress(wrd.getSendingaddress().trim());
            wtr.setCoinType(COIN_TYPE_USDT);
            wtr.setVersion(VERSION);
            wtr.setWalletId(WLLETID);
            wtr.setTxType(wrd.getTx_type());
            wtr.setMinerFee(Long.parseLong(new DecimalFormat().format(wrd.getFee()*Math.pow(10,8)).replaceAll(",","")));
            //向目标地址发送比特币
            wtr.setReserveFree(wrd.getSendtoaddressFree());
            wtr.setTxid(wrd.getTxid().trim());
            //存入数据库
            if(this.getList(wtr) !=null && this.getList(wtr).size()>0){
                wtr.setEntryId(this.getList(wtr).get(0).getEntryId());
                walletTransactionRecordMapper.updateByPrimaryKey(wtr);
            }else{
                walletTransactionRecordMapper.insert(wtr);
            }
            wtr.setEntryId(null);
            insertWalletFinanceList(wtr);
        }catch (Exception e){
            e.printStackTrace();
            log.error("存入数据失败：{}",e.getMessage());
        }

    }



    /**
     *查询wallet_transaction_record
     */
      private List<WalletTransactionRecord> getList(WalletTransactionRecord whe){
        List<WalletTransactionRecord> list=new ArrayList<>();
        try {
            list=walletTransactionRecordMapper.selectWalletTransactionList(whe);
            return list;
        }catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return list;
        }
    }
    /**
     *查询wallet_fiance
     */
    private List<WalletFinance> getFinanceList(WalletFinance wf){
        List<WalletFinance> list=new ArrayList<>();
        try {
            list=walletFinanceMapper.selectWalletFinanceList(wf);
            return list;
        }catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return list;
        }
    }
    //提现节点添加比特币来源
    private double getSendBitcoinWithdraw(String txid,String sendToddress){
        double sendBitcoin=0.00000000;
        try {
            JSONObject json=getRawTransactionWithdraw(txid);
            //根据tx_id查询交易信息
            if(json !=null){
                JSONObject TxObj = getRawTransactionWithdraw(txid).getJSONObject(RESULT);
                //输出地址voutaddress
                JSONArray vout = TxObj.getJSONArray("vout");
                if (vout!=null && vout.size() > 0) {
                    for (int j = 0; j < vout.size(); j++) {
                        //vout对象
                        String sp = vout.getJSONObject(j).getString("scriptPubKey");
                        ScriptPubKey scriptPubKey = JSON.parseObject(sp, ScriptPubKey.class);
                        if(scriptPubKey !=null && scriptPubKey.getAddresses() != null){
                            //存入商户热钱包
                            if ((scriptPubKey.getAddresses().toString()).replaceAll("\\[|\\]", "").equals(sendToddress)) {
                                sendBitcoin =Double.parseDouble( vout.getJSONObject(j).getString("value"));
                                return sendBitcoin;
                            }
                        }
                    }
                }
            }

        }catch (Exception e){
            e.printStackTrace();
            log.error("解析txid失败：{}",e.getMessage());
            return  sendBitcoin;
        }
        return sendBitcoin;
    }
}